home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 43 / Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso / -serious- / programming / other / python-1.52 / lib / site-python / arexx.py next >
Text File  |  1999-06-14  |  5KB  |  226 lines

  1. """
  2. High level ARexx interface.
  3. ©Irmen de Jong
  4.  
  5. $VER: ARexx.py 1.5 (3.1.99)
  6. """
  7.  
  8. import ARexxll
  9. import string
  10. import Dos
  11. import sys
  12.  
  13. error = ARexxll.error
  14.  
  15. errorstring = ARexxll.errorstring
  16.  
  17. # ARexx result codes:
  18. RC_OK    =  0  # success
  19. RC_WARN  =  5  # warning only
  20. RC_ERROR = 10  # something's wrong
  21. RC_FATAL = 20  # complete or severe failure
  22.  
  23.  
  24. #### PORT #################################
  25.  
  26. class port:
  27.     """
  28.     ARexx port base class.
  29.     IMPORTANT: Don't create objects of this class directly, use one of
  30.     the derived classes below (publicport or privateport)!!!
  31.     """
  32.     def __init__(self,name):
  33.         self.port = ARexxll.port(name)
  34.         self.signal = self.port.signal
  35.         if name:
  36.             self.name = self.port.name
  37.     def close(self):
  38.         self.port.close()
  39.     def wait(self):
  40.         self.port.wait()
  41.     def getmsg(self):
  42.         return self.port.getmsg()
  43.     def send(self,to,cmd,async=0):
  44.         self.flush()                        # XXX necessary?
  45.         if async:
  46.             self.port.send(to,cmd,1)        # no return value
  47.         else:
  48.             rc,rc2,result = self.port.send(to,cmd,0)
  49.             if rc:
  50.                 raise error, (rc,rc2)
  51.             else:
  52.                 return result
  53.     def flush(self):
  54.         while self.port.getmsg(): pass
  55.     def setstringmsgs(self,flag):
  56.         self.port.setstringmsgs(flag)
  57.     def settokenizeline(self,flag):
  58.         self.port.settokenizeline(flag)
  59.     
  60.  
  61.  
  62. class privateport(port):
  63.     """
  64.     Private ARexx port.
  65.     Meant for sending messages to other ports only.
  66.     """
  67.     def __init__(self):
  68.         port.__init__(self,None)
  69.  
  70.     # currently, inherits all methods of port superclass unchanged
  71.  
  72.  
  73. class publicport(port):
  74.     """
  75.     Public ARexx port.
  76.     For setting up your own host.
  77.     """
  78.     def __init__(self,name='PYTHON'):
  79.         name=string.upper(name)
  80.         for c in name:
  81.             if not c in '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_.':
  82.                 raise ValueError,'invalid port name'
  83.         port.__init__(self,name)
  84.  
  85.     # currently, inherits all methods of port superclass unchanged
  86.  
  87.  
  88. #### HOST ##################################
  89.  
  90. class host(publicport):
  91.     """
  92.     ARexx host class.
  93.     For setting up your complete ARexx host system.
  94.     Automatic parsing & dispatching of command lines.
  95.     """
  96.     def __init__(self,name='PYTHON',cmds=None):
  97.         publicport.__init__(self,name)
  98.         self.commands = {}
  99.         self.setcommand('HELP','COMMAND,STEM/K,VAR/K',None,std_help_func)
  100.         self.cmderror='Unknown command'
  101.         self.catch = 0
  102.         if cmds: self.setcommands(cmds)
  103.     def __repr__(self):
  104.         if hasattr(self,'name'):
  105.             return '<host instance, port '+self.name+'>'
  106.         else:
  107.             return '<host instance, defunct>'
  108.     def close(self):
  109.         if hasattr(self,'port'):
  110.             self.port.close()
  111.             del self.name
  112.             del self.port
  113.             del self.commands
  114.     def setcommands(self,cmds):
  115.         for (c,t,d,f) in cmds:
  116.             self.setcommand(c,t,d,f)
  117.     def setcommand(self,cmd,template,defaults,func):
  118.         if template==None: parser=None
  119.         else: parser=Dos.ArgParser(template)
  120.         self.commands[string.upper(cmd)]=(parser,func)
  121.         if defaults: self.setdefaults(cmd,defaults)
  122.     def setdefaults(self,cmd,defaults):
  123.         parser=self.commands[cmd][0]
  124.         if parser.defaults.keys()==defaults.keys():
  125.             parser.defaults=defaults
  126.         else:
  127.             raise ValueError,'incompatible defaults'
  128.     def defaults(self,cmd):
  129.         return self.commands[cmd][0].defaults
  130.     def catchExceptions(self,yes):
  131.         self.catch = yes
  132.     def dispatch(self):
  133.         m=self.port.getmsg()
  134.         res=-1
  135.         if m and m.msg:
  136.             i=string.index(m.msg+' ',' ')
  137.             cmd=string.upper(m.msg[:i])
  138.             args=m.msg[i+1:]
  139.             try:
  140.                 try:
  141.                     (parser,func) = self.commands[cmd]
  142.                 except KeyError:
  143.                     m.rc=RC_FATAL; m.rc2=self.cmderror
  144.                 else:
  145.                     if parser:
  146.                         res=func(self,m,cmd,parser.parse(args))
  147.                     else:
  148.                         res=func(self,m,cmd,args)
  149.             except Dos.error,str:
  150.                 m.rc=RC_ERROR; m.rc2=str[0]    # ReadArgs() probably failed
  151.             except:
  152.                 if self.catch:
  153.                     m.rc=RC_ERROR; m.rc2='Unhandled exception '+sys.exc_type+' : '+sys.exc_value
  154.                 else:
  155.                     print '*** Unhandled exception during ARexx cmd dispatch ***'
  156.                     raise sys.exc_type,sys.exc_value,sys.exc_traceback # re-raise exception
  157.             m.reply()
  158.         return res
  159.     def run(self):
  160.         self.flush()
  161.         while 1:
  162.             self.wait()
  163.             if not self.dispatch(): break
  164.     def flush(self):
  165.         while self.dispatch()!=-1: pass       # overrides publicport.flush
  166.  
  167.  
  168.  
  169. def std_help_func(host,msg,cmd,args):
  170.     var = args['VAR']
  171.     stem = args['STEM']
  172.     if args['COMMAND']:
  173.         try:
  174.             # return template for command
  175.             helpc=string.upper(args['COMMAND'])
  176.             parser=host.commands[helpc][0]
  177.             if parser:
  178.                 result=[parser.template]
  179.             else:
  180.                 result=['ARGS/F']
  181.         except KeyError:
  182.             msg.rc=RC_ERROR; msg.rc2='No help on command (unknown)'
  183.             return 1
  184.     else:
  185.         # return no. of commands followed by the commands.
  186.         cmds = host.commands.keys()
  187.         cmds.sort()
  188.         result = [`len(host.commands)`]+cmds
  189.     if var:
  190.         msg.setvar(var,string.join(result))
  191.     elif stem:
  192.         if len(result)==1:
  193.             msg.setvar(stem+'COUNT','1')
  194.             msg.setvar(stem+'1',result[0])
  195.         else:
  196.             msg.setvar(stem+'COUNT',result[0])
  197.             del result[0]
  198.             i=1
  199.             for c in result:
  200.                 msg.setvar(stem+`i`,c); i=i+1
  201.     else:
  202.         msg.result=string.join(result)
  203.     return 1
  204.  
  205. def std_debug_func(host,msg,cmd,args):
  206.     print 'DEBUG FUNCTION'
  207.     print 'HOST =',host
  208.     print 'MSG  =',msg
  209.     print 'CMD  =',cmd
  210.     print 'ARGS =',args
  211.     print 'RETURNING \'the result\''
  212.     msg.result='the result'
  213.     return 1
  214.  
  215.  
  216. ##### MISC UTILITY FUNCTIONS ###########################33
  217.  
  218. def SendARexxMsg(Port, Message):
  219.  return privateport().send(Port, Message)
  220.  
  221. def CallARexxFunc(Func, *Args):
  222.  return SendARexxMsg('REXX',
  223.     '"Return '+Func+'('+reduce(lambda x,y: x+','+`y`,Args,'')[1:]+')')
  224.  
  225.  
  226.